"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExcelDateUtil = void 0;
const XLSX = __importStar(require("xlsx"));
/**
 * Excel日期解析工具类
 * 处理Excel中的日期序列号转换为JavaScript Date对象
 */
class ExcelDateUtil {
    /**
     * 将Excel日期序列号转换为Date对象
     * @param value Excel中的日期值（可能是序列号或日期字符串）
     * @returns Date对象
     */
    static parseExcelDate(value) {
        if (!value) {
            throw new Error('日期值不能为空');
        }
        // 如果已经是Date对象，直接返回
        if (value instanceof Date) {
            return value;
        }
        const stringValue = String(value).trim();
        // 检查是否为Excel日期序列号（纯数字）
        if (this.isExcelSerialNumber(stringValue)) {
            return this.convertExcelSerialToDate(Number(stringValue));
        }
        // 尝试解析为标准日期格式，优先处理常见的Excel日期格式
        let parsedDate = this.parseChineseDateFormat(stringValue);
        if (!parsedDate) {
            // 如果自定义解析失败，尝试标准解析
            parsedDate = new Date(stringValue);
            if (isNaN(parsedDate.getTime())) {
                throw new Error(`无法解析的日期格式: ${stringValue}`);
            }
        }
        return parsedDate;
    }
    /**
     * 检查是否为Excel日期序列号
     * @param value 字符串值
     * @returns 是否为序列号
     */
    static isExcelSerialNumber(value) {
        // 检查是否为纯数字（包括小数）
        const numberPattern = /^\d+(\.\d+)?$/;
        if (!numberPattern.test(value)) {
            return false;
        }
        const num = Number(value);
        // Excel日期序列号范围：大于25569（1970-01-01）的数字更可能是Excel序列号
        // 这个阈值可以避免将普通数字误认为是日期序列号
        return num > 25569 && num <= 2958465;
    }
    /**
     * 将Excel序列号转换为Date对象
     * @param serialNumber Excel日期序列号
     * @returns Date对象
     */
    static convertExcelSerialToDate(serialNumber) {
        try {
            // 使用XLSX库的内置方法解析Excel日期序列号
            const dateObj = XLSX.SSF.parse_date_code(serialNumber);
            // 创建Date对象，注意月份需要减1（JavaScript月份从0开始）
            const resultDate = new Date(dateObj.y, // 年
            dateObj.m - 1, // 月（减1）
            dateObj.d, // 日
            dateObj.H || 0, // 时
            dateObj.M || 0, // 分
            dateObj.S || 0 // 秒
            );
            console.log(`🔢 Excel序列号转换: ${serialNumber} -> ${resultDate.toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' })}`);
            return resultDate;
        }
        catch (error) {
            console.error(`❌ Excel序列号转换失败: ${serialNumber}`, error);
            throw new Error(`Excel序列号转换失败: ${serialNumber}`);
        }
    }
    /**
     * 解析中文日期格式
     * @param dateString 日期字符串
     * @returns Date对象或null
     */
    static parseChineseDateFormat(dateString) {
        if (!dateString)
            return null;
        // 替换中文分隔符和特殊字符
        let normalizedStr = dateString
            .replace(/年/g, '-')
            .replace(/月/g, '-')
            .replace(/日/g, ' ')
            .replace(/时/g, ':')
            .replace(/分/g, '')
            .replace(/秒/g, '')
            .replace(/\s+/g, ' ')
            .trim();
        // 支持的时间格式模式
        const patterns = [
            // 2025/6/27 03:00:00 或 2025/6/27 3:00:00
            {
                regex: /^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{2}):(\d{2})$/,
                handler: (match) => {
                    const [, year, month, day, hour, minute, second] = match;
                    return new Date(parseInt(year), parseInt(month) - 1, parseInt(day), parseInt(hour), parseInt(minute), parseInt(second));
                }
            },
            // 2025/6/27 3:00 或 2025/6/27 03:00
            {
                regex: /^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{2})$/,
                handler: (match) => {
                    const [, year, month, day, hour, minute] = match;
                    return new Date(parseInt(year), parseInt(month) - 1, parseInt(day), parseInt(hour), parseInt(minute));
                }
            },
            // 2025-06-27 08-35
            {
                regex: /^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2})-(\d{2})$/,
                handler: (match) => {
                    const [, year, month, day, hour, minute] = match;
                    return new Date(parseInt(year), parseInt(month) - 1, parseInt(day), parseInt(hour), parseInt(minute));
                }
            },
            // 2025-06-27 08:35 或 2025-6-27 8:35
            {
                regex: /^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{2})$/,
                handler: (match) => {
                    const [, year, month, day, hour, minute] = match;
                    return new Date(parseInt(year), parseInt(month) - 1, parseInt(day), parseInt(hour), parseInt(minute));
                }
            },
            // 2025/6/27 或 2025-6-27 (只有日期)
            {
                regex: /^(\d{4})[-\/](\d{1,2})[-\/](\d{1,2})$/,
                handler: (match) => {
                    const [, year, month, day] = match;
                    return new Date(parseInt(year), parseInt(month) - 1, parseInt(day), 0, 0);
                }
            },
            // mm/dd/yyyy hh:mm 格式
            {
                regex: /^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{2})$/,
                handler: (match) => {
                    const [, month, day, year, hour, minute] = match;
                    return new Date(parseInt(year), parseInt(month) - 1, parseInt(day), parseInt(hour), parseInt(minute));
                }
            }
        ];
        // 尝试匹配所有模式
        for (const pattern of patterns) {
            const match = normalizedStr.match(pattern.regex);
            if (match) {
                const date = pattern.handler(match);
                if (!isNaN(date.getTime())) {
                    console.log(`📅 日期解析成功: ${dateString} -> ${date.toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' })}`);
                    return date;
                }
            }
        }
        // 回退处理：使用Date构造函数
        let fallbackStr = normalizedStr
            .replace(/\//g, '-')
            .replace(/(\d{4}-\d{1,2}-\d{1,2})\s+(\d{1,2})-(\d{2})/, '$1 $2:$3')
            .replace(/(\d{1,2}:\d{2}):\d{2}/, '$1');
        const date = new Date(fallbackStr);
        if (!isNaN(date.getTime())) {
            console.log(`📅 回退解析成功: ${dateString} -> ${date.toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' })}`);
            return date;
        }
        return null;
    }
    /**
     * 格式化日期为字符串
     * @param date Date对象
     * @param format 格式类型
     * @returns 格式化后的日期字符串
     */
    static formatDate(date, format = 'iso') {
        switch (format) {
            case 'iso':
                return date.toISOString();
            case 'local':
                return date.toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' });
            case 'date-only':
                return date.toISOString().split('T')[0];
            default:
                return date.toISOString();
        }
    }
}
exports.ExcelDateUtil = ExcelDateUtil;
